package util
{
	//声音播放
	
	import flash.events.Event;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	
	import flash3.framework.Map;
	import flash3.framework.Singleton;
	
	import global.Resource;
	
	public class SoundManager
	{
		private var soundChannel:Array;
		private var musicChannel:SoundChannel;
		private var soundTransform:SoundTransform;
		private var musicTransform:SoundTransform;
		private var curMusicName:String;
		private var soundMap:Map;
		
		private static const MAX_CHANNEL:uint = 32;
		private static const MAX_MUSIC_LOOP_COUNT:uint = 10000;
		
		private static const SOUND_TYPE_SOUND:uint = 0;	//音效
		private static const SOUND_TYPE_MUSIC:uint = 1;	//音乐
		
		public function SoundManager()
		{
			soundMap = new Map();
			soundChannel = [];
			soundTransform = new SoundTransform();
			musicTransform = new SoundTransform();
			
			register("BOMB",SOUND_TYPE_SOUND);
			register("BRIGHT_CARD",SOUND_TYPE_SOUND);
			register("CALL_CARD",SOUND_TYPE_SOUND);
			register("DISPATCH_CARD",SOUND_TYPE_SOUND);
			register("GAME_END",SOUND_TYPE_SOUND);
			register("GAME_LOST",SOUND_TYPE_SOUND);
			register("GAME_START",SOUND_TYPE_SOUND);
			register("GAME_WARN",SOUND_TYPE_SOUND);
			register("GAME_WIN",SOUND_TYPE_SOUND);
			register("GIVE_UP_SCORE",SOUND_TYPE_SOUND);
			register("MOST_CARD",SOUND_TYPE_SOUND);
			register("NOT_SNATCH_LAND",SOUND_TYPE_SOUND);
			register("ONE_SCORE",SOUND_TYPE_SOUND);
			register("OUT_CARD",SOUND_TYPE_SOUND);
			register("PASS_CARD",SOUND_TYPE_SOUND);
			register("SNATCH_LAND",SOUND_TYPE_SOUND);
			register("THREE_SCORE",SOUND_TYPE_SOUND);
			register("TWO_SCORE",SOUND_TYPE_SOUND);
			register("WARMING_CARD",SOUND_TYPE_SOUND);
		}
		
		static public function get i():SoundManager
		{
			return Singleton.getInstanceOrCreate(SoundManager) as SoundManager;
		}
		
		public function register(soundName:String, soundType:uint, cls:Class=null):void
		{
//			soundMap.put(soundName, {soundType:soundType, cls:cls});
			soundMap.put(soundName, {soundType:soundType, cls:Resource.i.getClass("sound", soundName)});
		}
		
		public function getSoundStatus(soundName:String):Object
		{
			if(!soundMap.containsKey(soundName))
				throw new Error("未知的声音！");
			
			var soundInfo:Object = soundMap.getValue(soundName);
			var soundStatus:Object = {};
			soundStatus.sound = new (soundInfo.cls as Class);
			soundStatus.soundType =soundInfo.soundType;
			
			return soundStatus;
		}
		
		public function getSoundType(soundName:String):uint
		{
			if(!soundMap.containsKey(soundName))
				throw new Error("未知的声音！");
			
			return soundMap.getValue(soundName).soundType;
		}
		
		public function play(soundName:String, loops:uint = 0):void
		{
			var channel:SoundChannel = null;
			var soundStatus:Object = getSoundStatus(soundName);
			
			if(soundChannel.length > MAX_CHANNEL)
				throw new Error("没有声卡或者声道已经被用完！");
			
			if(curMusicName != soundStatus.soundName)
				return;
			
			if(soundStatus.soundType == SOUND_TYPE_SOUND)
			{
				channel = soundStatus.sound.play(0, loops, soundTransform);
				if(channel)
				{
					channel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
					soundChannel.push({soundName:soundName, channel:channel});
				}
			}
			else if(soundStatus.soundType == SOUND_TYPE_MUSIC)
			{
				if(musicChannel != null)
					musicChannel.stop();
				musicChannel = soundStatus.sound.play(0, 10000, musicTransform);
				curMusicName = soundStatus.soundName;
			}
		}
		
		private function soundCompleteHandler(event:Event) : void
		{
			(event.target as SoundChannel).removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
			
			for( var i:uint = 0; i < soundChannel.length; i++) 
			{			
				if (soundChannel[i].channel == event.target)
				{
					soundChannel.splice(i, 1);
					break;
				}
			}
		}
		
		public function stop(soundName:String):void
		{
			var soundType:uint = getSoundType(soundName);
			if(soundType == SOUND_TYPE_SOUND)
				stopSound(soundName);
			else if(soundType == SOUND_TYPE_SOUND)
				stopMusic();
		}
		
		public function stopMusic():void
		{
			if(musicChannel != null)
				musicChannel.stop();
		}
		
		public function stopSound(soundName:String):void
		{
			for(var i:uint = 0; i < soundChannel.length; i++) 
			{
				if (soundChannel[i].soundName == soundName)
				{
					soundChannel[i].channel.removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
					soundChannel[i].channel.stop();
					soundChannel.splice(i, 1);
				}
			}
		}
		
		public function stopAll(music:Boolean = true, sound:Boolean = true):void
		{
			if(sound)
			{
				for (var i:uint = 0; i < soundChannel.length; i++)
				{
					soundChannel[i].channel.removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
					soundChannel[i].channel.stop();
				}
				soundChannel.length = 0;
			}
			
			if(music)
				stopMusic();
		}
		public function setMusicVolume(volume:Number):void
		{
			musicTransform.volume = volume;
			if(musicTransform != null)
				musicChannel.soundTransform = musicTransform; 
		}
		
		public function getMusicVolume():Number
		{
			return musicTransform.volume;
		}
		
		public function setSoundVolume(volume:Number):void
		{
			soundTransform.volume = volume;
			for (var i:uint = 0; i < soundChannel.length; i++)
				soundChannel[i].channel.soundTransform = soundTransform;
		}
		
		public function getSoundVolume():Number
		{
			return soundTransform.volume;
		}
	}
}